package cn.changsheng.csfenjie.utils;

import org.bukkit.command.*;
import org.bukkit.event.player.*;
import org.bukkit.inventory.*;
import org.bukkit.event.block.*;
import org.bukkit.entity.*;
import java.lang.reflect.*;
import java.text.*;
import java.util.*;
import org.bukkit.scheduler.*;

import cn.changsheng.csfenjie.main;

import org.bukkit.*;
import org.bukkit.plugin.*;
import org.bukkit.configuration.file.*;
import java.io.*;

public class CommonlyUtil
{
    public static boolean opUseCommand(final CommandSender player) {
        return !player.isOp();
    }
    
    public static boolean consoleUse(final CommandSender sender) {
        return !(sender instanceof Player);
    }
    
    public static String createRandomString(final int length) {
        String number = "";
        final Random random = new Random();
        for (int i = 0; i < length; ++i) {
            final String str = (random.nextInt(2) % 2 == 0) ? "num" : "char";
            if ("char".equalsIgnoreCase(str)) {
                final int nextInt = (random.nextInt(2) % 2 == 0) ? 65 : 97;
                number += (char)(nextInt + random.nextInt(26));
            }
            else {
                number += String.valueOf(random.nextInt(10));
            }
        }
        return number;
    }
    
    public static int backpackEmptyNumber(final Player player) {
        int number = 0;
        int empty = 0;
        while (number <= 35) {
            if (player.getInventory().getItem(number) == null) {
                ++empty;
            }
            ++number;
        }
        return empty;
    }
    
    public static void giveExp(final Player player, final int xp) {
        int level;
        int toNextLevel;
        int floatExp;
        for (level = player.getLevel(), toNextLevel = getUpgradeExp(level), floatExp = (int)(player.getExp() * toNextLevel) + xp; floatExp >= toNextLevel; floatExp -= toNextLevel, toNextLevel = getUpgradeExp(++level)) {}
        while (floatExp < 0) {
            floatExp += (toNextLevel = getUpgradeExp(--level));
            if (level < 0) {
                floatExp = (level = 0);
            }
        }
        player.setLevel(level);
        player.setExp(floatExp / (float)toNextLevel);
        player.setTotalExperience(getTotalExp(level) + floatExp);
    }
    
    public static int getUpgradeExp(final int level) {
        return (level < 16) ? (level * 2 + 7) : ((level < 30) ? (level * 5 - 38) : (level * 9 - 158));
    }
    
    public static int getTotalExp(final int level) {
        return (int)((level < 17) ? (level * (level + 6)) : ((level < 31) ? (level * (level * 2.5 - 40.5) + 360.0) : (level * (level * 4.5 - 162.5) + 2220.0)));
    }
    
    public static void giveitem(final Player player, final ItemStack item) {
        if (item == null || item.getType() == Material.AIR) {
            return;
        }
        for (final ItemStack i : player.getInventory().addItem(new ItemStack[] { item }).values()) {
            player.getWorld().dropItemNaturally(player.getLocation(), item);
        }
    }
    
    public static Boolean emptyItem(final Player player) {
        return player.getInventory().getItemInHand() == null || player.getInventory().getItemInHand().getType() == Material.AIR;
    }
    
    public static String getItemNBT(final ItemStack item) {
        final String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
        try {
            final Class<?> saveitem = Class.forName("net.minecraft.server." + version + ".ItemStack");
            final Class<?> itemstack = Class.forName("org.bukkit.craftbukkit." + version + ".inventory.CraftItemStack");
            final Class<?> nbttagcompound = Class.forName("net.minecraft.server." + version + ".NBTTagCompound");
            final Method asNMSCopy = itemstack.getMethod("asNMSCopy", ItemStack.class);
            final Method save = saveitem.getMethod("save", nbttagcompound);
            final Object tag = nbttagcompound.newInstance();
            final Object nmsitem = asNMSCopy.invoke(null, item);
            final Object saves = save.invoke(nmsitem, tag);
            return saves.toString();
        }
        catch (Exception e) {
            e.printStackTrace();
            return "null";
        }
    }
    
    public static List<String> listReplace(final List<String> list, final String wasReplaced, final String replace) {
        final ArrayList<String> news = new ArrayList<String>();
        for (final String s : list) {
            news.add(s.replace(wasReplaced, replace));
        }
        return news;
    }
    
    public static boolean getInteractHand(final PlayerInteractEvent evt) {
        return evt.getHand() == null || !evt.getHand().equals((Object)EquipmentSlot.HAND);
    }
    
    public static boolean getPlaceHand(final BlockPlaceEvent evt) {
        return evt.getHand() == null || !evt.getHand().equals((Object)EquipmentSlot.HAND);
    }
    
    public static double percentageNumber(final String percentage) {
        try {
            return Double.parseDouble(percentage.replace("%", "")) / 100.0;
        }
        catch (Exception b) {
            return 9.99;
        }
    }
    
    public static double percentage(double number, final String percentage) {
        try {
            number *= Double.parseDouble(percentage.replace("%", "")) / 100.0;
        }
        catch (Exception a) {
            return 9.99;
        }
        return number;
    }
    
    public static void telePortChunk(final Player player, final World world, final Chunk chunk) {
        final Location location = player.getLocation();
        location.setWorld(world);
        final double x = chunk.getX() * 16;
        final double z = chunk.getZ() * 16;
        location.setX(x);
        location.setZ(z);
        location.setY((double)world.getHighestBlockAt(location).getY());
        player.teleport(location);
    }
    
    public static int playerNumber(final World world) {
        int i = 0;
        for (final Entity entity : world.getEntities()) {
            if (entity instanceof Player) {
                ++i;
            }
        }
        return i;
    }
    
    public static double getMS() {
        final String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
        try {
            final Class<?> minecraftserver = Class.forName("net.minecraft.server." + version + ".MinecraftServer");
            final Method getserver = minecraftserver.getMethod("getServer", (Class<?>[])new Class[0]);
            final Class<?> c = getserver.invoke(minecraftserver, new Object[0]).getClass();
            Field h = null;
            for (final Field field : c.getFields()) {
                if (field.getType().getName().equalsIgnoreCase("[J")) {
                    h = field;
                    break;
                }
            }
            long average = 0L;
            for (final long b : (long[])h.get(getserver.invoke(minecraftserver, new Object[0]))) {
                average += b;
            }
            average /= ((long[])h.get(getserver.invoke(minecraftserver, new Object[0]))).length;
            return average * 1.0E-6;
        }
        catch (Exception a) {
            return 0.0;
        }
    }
    
    public static double getTPS() {
        final String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
        try {
            final Class<?> minecraftserver = Class.forName("net.minecraft.server." + version + ".MinecraftServer");
            final Method getserver = minecraftserver.getMethod("getServer", (Class<?>[])new Class[0]);
            Field h = null;
            for (final Field field : minecraftserver.getFields()) {
                if (field.getType().getName().equalsIgnoreCase("[J")) {
                    h = field;
                    break;
                }
            }
            long average = 0L;
            for (final long b : (long[])h.get(getserver.invoke(minecraftserver, new Object[0]))) {
                average += b;
            }
            average /= ((long[])h.get(getserver.invoke(minecraftserver, new Object[0]))).length;
            return Math.min(1000.0 / (average * 1.0E-6), 20.0);
        }
        catch (Exception a) {
            return 0.0;
        }
    }
    
    public static int randomNumber(final int min, final int max) {
        return new Random().nextInt(max - min + 1) + min;
    }
    
    public static int getMonthDay() {
        final String timegroup = new SimpleDateFormat("yyyy:MM").format(new Date());
        final int nowYear = Integer.parseInt(timegroup.split(":")[0]);
        final int nowMonth = Integer.parseInt(timegroup.split(":")[1]);
        if (nowMonth == 1 || nowMonth == 3 || nowMonth == 5 || nowMonth == 7 || nowMonth == 8 || nowMonth == 10 || nowMonth == 12) {
            return 31;
        }
        if (nowMonth != 2) {
            return 30;
        }
        if (nowYear % 4 == 0 && nowYear % 100 != 0) {
            return 29;
        }
        return 28;
    }
    
    public static int getMonthDay(final int nowMonth) {
        final String timegroup = new SimpleDateFormat("yyyy").format(new Date());
        final int nowYear = Integer.parseInt(timegroup.split(":")[0]);
        if (nowMonth == 1 || nowMonth == 3 || nowMonth == 5 || nowMonth == 7 || nowMonth == 8 || nowMonth == 10 || nowMonth == 12) {
            return 31;
        }
        if (nowMonth != 2) {
            return 30;
        }
        if (nowYear % 4 == 0 && nowYear % 100 != 0) {
            return 29;
        }
        return 28;
    }
    
    public static int getMonthDay(final int nowMonth, final int nowYear) {
        if (nowMonth == 1 || nowMonth == 3 || nowMonth == 5 || nowMonth == 7 || nowMonth == 8 || nowMonth == 10 || nowMonth == 12) {
            return 31;
        }
        if (nowMonth != 2) {
            return 30;
        }
        if (nowYear % 4 == 0 && nowYear % 100 != 0) {
            return 29;
        }
        return 28;
    }
    
    public static String getTime() {
        final String timegroup = new SimpleDateFormat("yyyy:MM:dd:HH:mm").format(new Date());
        final int nowYear = Integer.parseInt(timegroup.split(":")[0]);
        final int nowMonth = Integer.parseInt(timegroup.split(":")[1]);
        final int nowDay = Integer.parseInt(timegroup.split(":")[2]);
        final int nowHour = Integer.parseInt(timegroup.split(":")[3]);
        final int nowMinute = Integer.parseInt(timegroup.split(":")[4]);
        return nowYear + ":" + nowMonth + ":" + nowDay + ":" + nowHour + ":" + nowMinute;
    }
    
    public static String getTime(final int m) {
        final String timegroup = new SimpleDateFormat("yyyy:MM:dd:HH:mm").format(new Date());
        final int nowYear = Integer.parseInt(timegroup.split(":")[0]);
        final int nowMonth = Integer.parseInt(timegroup.split(":")[1]);
        final int nowDay = Integer.parseInt(timegroup.split(":")[2]);
        final int nowHour = Integer.parseInt(timegroup.split(":")[3]);
        final int nowMinute = Integer.parseInt(timegroup.split(":")[4]);
        int monthday = getMonthDay();
        int minute = m + nowMinute;
        int hour = nowHour;
        int day = nowDay;
        int month = nowMonth;
        int year = nowYear;
        if (minute >= 60) {
            hour += minute / 60;
            minute %= 60;
        }
        if (hour >= 24) {
            day += hour / 24;
            hour %= 24;
        }
        if (day > monthday) {
            int t_d = day;
            int t_m = month;
            int t_y = year;
            boolean first = true;
            while (t_d - monthday > 0) {
                first = false;
                ++month;
                t_d -= monthday;
                if (++t_m > 12) {
                    t_m = 1;
                    ++t_y;
                }
                monthday = getMonthDay(t_m, t_y);
            }
            if (t_d - monthday != 0 && first) {
                ++month;
            }
            day = t_d;
        }
        if (month > 12) {
            year += month / 12;
            month %= 12;
        }
        return year + ":" + month + ":" + day + ":" + hour + ":" + minute;
    }
    
    public static String getTime(final int m, final int h) {
        final String timegroup = new SimpleDateFormat("yyyy:MM:dd:HH:mm").format(new Date());
        final int nowYear = Integer.parseInt(timegroup.split(":")[0]);
        final int nowMonth = Integer.parseInt(timegroup.split(":")[1]);
        final int nowDay = Integer.parseInt(timegroup.split(":")[2]);
        final int nowHour = Integer.parseInt(timegroup.split(":")[3]);
        final int nowMinute = Integer.parseInt(timegroup.split(":")[4]);
        int monthday = getMonthDay();
        int minute = m + nowMinute;
        int hour = h + nowHour;
        int day = nowDay;
        int month = nowMonth;
        int year = nowYear;
        if (minute >= 60) {
            hour += minute / 60;
            minute %= 60;
        }
        if (hour >= 24) {
            day += hour / 24;
            hour %= 24;
        }
        if (day > monthday) {
            int t_d = day;
            int t_m = month;
            int t_y = year;
            boolean first = true;
            while (t_d - monthday > 0) {
                first = false;
                ++month;
                t_d -= monthday;
                if (++t_m > 12) {
                    t_m = 1;
                    ++t_y;
                }
                monthday = getMonthDay(t_m, t_y);
            }
            if (t_d - monthday != 0 && first) {
                ++month;
            }
            day = t_d;
        }
        if (month > 12) {
            year += month / 12;
            month %= 12;
        }
        return year + ":" + month + ":" + day + ":" + hour + ":" + minute;
    }
    
    public static String getTime(final int m, final int h, final int d) {
        final String timegroup = new SimpleDateFormat("yyyy:MM:dd:HH:mm").format(new Date());
        final int nowYear = Integer.parseInt(timegroup.split(":")[0]);
        final int nowMonth = Integer.parseInt(timegroup.split(":")[1]);
        final int nowDay = Integer.parseInt(timegroup.split(":")[2]);
        final int nowHour = Integer.parseInt(timegroup.split(":")[3]);
        final int nowMinute = Integer.parseInt(timegroup.split(":")[4]);
        int monthday = getMonthDay();
        int minute = m + nowMinute;
        int hour = h + nowHour;
        int day = d + nowDay;
        int month = nowMonth;
        int year = nowYear;
        if (minute >= 60) {
            hour += minute / 60;
            minute %= 60;
        }
        if (hour >= 24) {
            day += hour / 24;
            hour %= 24;
        }
        if (day > monthday) {
            int t_d = day;
            int t_m = month;
            int t_y = year;
            boolean first = true;
            while (t_d - monthday > 0) {
                first = false;
                ++month;
                t_d -= monthday;
                if (++t_m > 12) {
                    t_m = 1;
                    ++t_y;
                }
                monthday = getMonthDay(t_m, t_y);
            }
            if (t_d - monthday != 0 && first) {
                ++month;
            }
            day = t_d;
        }
        if (month > 12) {
            year += month / 12;
            month %= 12;
        }
        return year + ":" + month + ":" + day + ":" + hour + ":" + minute;
    }
    
    public static String getDay(final int m) {
        int minute = m;
        int hour = 0;
        int day = 0;
        if (minute >= 60) {
            hour += minute / 60;
            minute %= 60;
        }
        if (hour >= 24) {
            day += hour / 24;
            hour %= 24;
        }
        return day + ":" + hour + ":" + minute;
    }
    
    public static String getDay(final int m, final int h) {
        int minute = m;
        int hour = h;
        int day = 0;
        if (minute >= 60) {
            hour += minute / 60;
            minute %= 60;
        }
        if (hour >= 24) {
            day += hour / 24;
            hour %= 24;
        }
        return day + ":" + hour + ":" + minute;
    }
    
    public static String getDay(final int m, final int h, final int d) {
        int minute = m;
        int hour = h;
        int day = d;
        if (minute >= 60) {
            hour += minute / 60;
            minute %= 60;
        }
        if (hour >= 24) {
            day += hour / 24;
            hour %= 24;
        }
        return day + ":" + hour + ":" + minute;
    }
    
    public static void sendActionBar(final Player player, final String m, int time) {
        if (time < 3) {
            time = 3;
        }
        final int finalTime = time;
        new BukkitRunnable() {
            int i = 0;
            
            public void run() {
                try {
                    final String version = Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3];
                    final Field playerConnection = Class.forName("net.minecraft.server." + version + ".EntityPlayer").getField("playerConnection");
                    final Class<?> packetPlayOutChat = Class.forName("net.minecraft.server." + version + ".PacketPlayOutChat");
                    final Method send = Class.forName("net.minecraft.server." + version + ".PlayerConnection").getMethod("sendPacket", Class.forName("net.minecraft.server." + version + ".Packet"));
                    final Method getHandle = Class.forName("org.bukkit.craftbukkit." + version + ".entity.CraftPlayer").getMethod("getHandle", (Class<?>[])new Class[0]);
                    final Class<?> iChatBaseComponent = Class.forName("net.minecraft.server." + version + ".IChatBaseComponent");
                    final Class<?> chatComponentText = Class.forName("net.minecraft.server." + version + ".ChatComponentText");
                    final Class<?> chatMessageType = Class.forName("net.minecraft.server." + version + ".ChatMessageType");
                    Enum e = null;
                    for (final Enum inside_enum : (Enum[])chatMessageType.getEnumConstants()) {
                        if (inside_enum.name().equalsIgnoreCase("GAME_INFO")) {
                            e = inside_enum;
                            break;
                        }
                    }
                    final Object message = chatComponentText.getConstructor(String.class).newInstance(ChatColor.translateAlternateColorCodes('&', m));
                    Object packet;
                    try {
                        packet = packetPlayOutChat.getConstructor(iChatBaseComponent, chatMessageType).newInstance(message, e);
                    }
                    catch (Exception a) {
                        packet = packetPlayOutChat.getConstructor(iChatBaseComponent, chatMessageType, player.getUniqueId().getClass()).newInstance(message, e, player.getUniqueId());
                    }
                    send.invoke(playerConnection.get(getHandle.invoke(player, new Object[0])), packet);
                }
                catch (Exception e2) {
                    e2.printStackTrace();
                    player.sendMessage("§c版本/服务端不兼容");
                }
                ++this.i;
                if (this.i >= finalTime - 2) {
                    this.cancel();
                }
            }
        }.runTaskTimerAsynchronously(main.getInstance(), 0L, 20L);
    }
    
    
    /**
     * 保存config
     * @param plugin
     * @param config
     * @param name
     */
    public static void saveConfig(final Plugin plugin, final FileConfiguration config, final String name) {
        new BukkitRunnable() {
            public void run() {
                try {
                    final File file = new File(plugin.getDataFolder(), name + ".yml");
                    config.save(file);
                }
                catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }.runTask(main.getInstance());
    }
}
